#include	"msp430g2231.h"
#include	"stdbool.h"

#define		TXD             BIT1    // TXD on P1.1
#define		RXD		        BIT2	// RXD on P1.2

#define     	Bit_time    	104 //104		// 9600 Baud, SMCLK=1MHz (1MHz/9600)=104
#define		    Bit_time_5	    52 //52		// Time for half a bit.

unsigned char BitCnt;
unsigned int TXByte;
unsigned int RXByte;

bool isReceiving;
bool hasReceived;

bool fall_trans = true;
unsigned int result[8];

#define SOUND result[0]
#define LIGHT result[2]
#define RESISTOR result[7]
#define light_threshold 0x8C
#define fall_threshold 0x2C


void Transmit(void);

void main(void)
{
	WDTCTL = WDTPW + WDTHOLD;		// Stop WDT

	BCSCTL1 = CALBC1_1MHZ;			// Set range
	DCOCTL = CALDCO_1MHZ;			// SMCLK = DCO = 1MHz

	P1SEL |= TXD;
	P1DIR |= TXD;

	P1DIR |= BIT6;   //LED init
	P1OUT ^= BIT6;

	P1IES |= RXD;				// RXD Hi/lo edge interrupt
	P1IFG &= ~RXD;				// Clear RXD (flag) before enabling interrupt
	P1IE |= RXD;				// Enable RXD interrupt

	isReceiving = false;
	hasReceived = false;
	
    ADC10CTL1 = INCH_7 + CONSEQ_1;                                     // A7/A5/A4/A3/A2/A1/A0, single sequence
    ADC10CTL0 = REF2_5V + ADC10SHT_2 + MSC+ REFON + ADC10ON + ADC10IE; //2.5 reference voltage
    ADC10DTC1 = 0x08;                                                  // 8 conversions
    ADC10AE0 |= BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT7;                    // A7/A5/A4/A3/A2/A1/A0
    P1DIR |= BIT6;                                                     // Set P1.6 output
    P1OUT &= ~BIT6;

	__bis_SR_register(GIE);			// interrupts enabled\

	while(1)
	{

	     ADC10CTL0 &= ~ENC;
	     while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
	     ADC10SA = (int)result;                  // Data buffer start
	     ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start

		if (hasReceived)
		{
			hasReceived = false;
			TXByte = RXByte;
			Transmit();
		}
		if (~hasReceived)
    			__bis_SR_register(CPUOFF + GIE);

	}
}

// Function Transmits Character from TXByte
void Transmit()
{
	while(isReceiving);

	P1OUT |= BIT6;  //LED P1.6 ON

  	CCTL0 = OUT;
  	TACTL = TASSEL_2 + MC_2;

  	BitCnt = 0xA;
  	CCR0 = TAR;

  	CCR0 += Bit_time;
  	TXByte |= 0x100;
  	TXByte = TXByte << 1;

  	CCTL0 =  CCIS0 + OUTMOD0 + CCIE;
  	while ( CCTL0 & CCIE );

  	P1OUT ^= BIT6;  //LED P1.6 OFF
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
	isReceiving = true;

	P1IE &= ~RXD;
	P1IFG &= ~RXD;

  	TACTL = TASSEL_2 + MC_2;
  	CCR0 = TAR;
  	CCR0 += Bit_time_5;
	CCTL0 = OUTMOD1 + CCIE;

	RXByte = 0;
	BitCnt = 0x9;
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
	if(!isReceiving)
	{
		CCR0 += Bit_time;
		if ( BitCnt == 0)
		{
  			TACTL = TASSEL_2;
			CCTL0 &= ~ CCIE ;
		}
		else
		{
			CCTL0 |=  OUTMOD2;
			if (TXByte & 0x01)
				CCTL0 &= ~ OUTMOD2;
			TXByte = TXByte >> 1;
			BitCnt --;
		}
	}
	else
	{
		CCR0 += Bit_time;
		if ( BitCnt == 0)
		{
  			TACTL = TASSEL_2;
			CCTL0 &= ~ CCIE ;

			isReceiving = false;

			P1IFG &= ~RXD;
			P1IE |= RXD;

			if ( (RXByte & 0x201) == 0x200)
			{
				RXByte = RXByte >> 1;
				RXByte &= 0xFF;
				hasReceived = true;
			}
  			__bic_SR_register_on_exit(CPUOFF);
		}
		else
		{
			if ( (P1IN & RXD) == RXD)
				RXByte |= 0x400;
			RXByte = RXByte >> 1;
			BitCnt --;
		}
	}
}

#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
	if (LIGHT < light_threshold)
		{
		P1OUT |= BIT6;
		} else {
	if (SOUND < fall_threshold) fall_trans = true;
    if ((SOUND > RESISTOR) && (fall_trans))
    	{
    	  P1OUT ^= BIT6;
    	  fall_trans = false;
    	}
	}

   // if ((SOUND > 0x12C) || (LIGHT > 0x12C) || (RESISTOR > 0x12C)) P1OUT |= BIT6; else P1OUT &= ~BIT6; //test string
	__bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}
